{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "0",
   "metadata": {},
   "source": [
    "# Currency Converter (Multi-Currency, Autonomous, API+SearchTool)\n",
    "This notebook demonstrates a fully autonomous, multi-currency conversion system built with [AG2 (AutoGen)](https://github.com/microsoft/autogen). It is inspired by the [original](https://github.com/ag2ai/ag2/blob/main/notebook/agentchat_function_call_currency_calculator.ipynb) USD↔EUR calculator but extended with:\n",
    "- Option to use GoogleSearchTool (inspired on [this](https://github.com/ag2ai/ag2/blob/main/notebook/tools_google_search.ipynb) notebook) **or** Frankfurter API for real-time exchange rates\n",
    "- Support for any currency pair\n",
    "- Fully autonomous multi-agent orchestration\n",
    "\n",
    "No human interaction needed once the user submits the initial prompt."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "1",
   "metadata": {},
   "source": [
    "## Installation\n",
    "\n",
    "To get started with the `Google Search` integration in AG2, follow these steps:\n",
    "\n",
    "Install AG2 with the `google-search` extra.\n",
    "Since our examples also use `openai` and `gemini`, install them as well:\n",
    "   \n",
    "```bash\n",
    "pip install -U ag2[openai,gemini,google-search]\n",
    "```\n",
    "> **Note:** If you have been using `autogen` or `ag2`, all you need to do is upgrade it using:  \n",
    "> ```bash\n",
    "> pip install -U autogen[openai,gemini,google-search]\n",
    "> ```\n",
    "> or  \n",
    "> ```bash\n",
    "> pip install -U ag2[openai,gemini,google-search]\n",
    "> ```\n",
    "> as `autogen`, and `ag2` are aliases for the same PyPI package.\n",
    "\n",
    "You're all set! Now you can start using Google Search with AG2.\n",
    "\n",
    "## Imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "import autogen\n",
    "from autogen import AssistantAgent\n",
    "from autogen.tools.experimental import GoogleSearchTool\n",
    "\n",
    "load_dotenv()\n",
    "\n",
    "from pathlib import Path\n",
    "\n",
    "from autogen.agentchat import initiate_group_chat\n",
    "from autogen.agentchat.group.patterns import AutoPattern\n",
    "from autogen.coding import LocalCommandLineCodeExecutor"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "3",
   "metadata": {},
   "source": [
    "## GoogleSearchTool with AG2 Google Search implementation\n",
    "\n",
    "For all other LLM providers or if you need to combine Google Search with other tools, follow this section to configure AG2’s implementation.\n",
    "\n",
    "### Setup Google Search Engine and API Key\n",
    "1. Create a Google Custom Search Engine (CSE):\n",
    "   - [Go to Google Programmable Search Engine](https://programmablesearchengine.google.com/about/)\n",
    "   - Click `Get Started` and create a search engine.\n",
    "   - Under `Sites to Search`, select `Search the entire web` if you want global search.\n",
    "   - Copy the **Search Engine ID** from the CSE dashboard  (`cx` parameter from the url)\n",
    "2. Get a Google API Key:\n",
    "   - Go to [Google Cloud Console](https://console.cloud.google.com/)\n",
    "   - Create a new project.\n",
    "   - Navigate to **APIs & Services > Library**, search for **Custom Search API** and enable it.\n",
    "   - Go to **APIs & Services > Credentials**, click on **Create Credentials > API key** and copy it.\n",
    "3. Export engine ID and api key\n",
    "    ```bash\n",
    "    export GOOGLE_SEARCH_ENGINE_ID=\"your_engine_id\"\n",
    "    export GOOGLE_SEARCH_API_KEY=\"your_api_key\"\n",
    "    ```\n",
    "\n",
    "### Agent Configuration"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4",
   "metadata": {},
   "outputs": [],
   "source": [
    "llm_config = autogen.LLMConfig(\n",
    "    config_list={\n",
    "        \"model\": \"gpt-5\",\n",
    "        \"api_type\": \"azure\",\n",
    "        \"api_key\": os.getenv(\"AZURE_OPENAI_API_KEY\"),\n",
    "        \"base_url\": os.getenv(\"BASE_URL\"),\n",
    "        \"api_version\": os.getenv(\"API_VERSION\"),\n",
    "    }\n",
    ")\n",
    "\n",
    "assistant = AssistantAgent(\n",
    "    name=\"assistant\",\n",
    "    llm_config={\"config_list\": llm_config.config_list},\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5",
   "metadata": {},
   "outputs": [],
   "source": [
    "workdir = Path(\"exchange_workspace\")\n",
    "workdir.mkdir(exist_ok=True)\n",
    "code_executor = LocalCommandLineCodeExecutor(work_dir=workdir)\n",
    "google_tool = GoogleSearchTool()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "6",
   "metadata": {},
   "source": [
    "### GoogleSearchTool Initialization\n",
    "\n",
    "Create `GoogleSearchTool` with your `search_api_key` and `search_engine_id`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7",
   "metadata": {},
   "outputs": [],
   "source": [
    "search_api_key = os.getenv(\"GOOGLE_SEARCH_API_KEY\")\n",
    "search_engine_id = os.getenv(\"GOOGLE_SEARCH_ENGINE_ID\")\n",
    "\n",
    "assert search_api_key is not None, \"Please set GOOGLE_SEARCH_API_KEY environment variable\"\n",
    "assert search_engine_id is not None, \"Please set GOOGLE_SEARCH_ENGINE_ID environment variable\"\n",
    "\n",
    "gs_tool = GoogleSearchTool(\n",
    "    search_api_key=search_api_key,\n",
    "    search_engine_id=search_engine_id,\n",
    ")\n",
    "# Once initialized, register the tool with the assistant:\n",
    "gs_tool.register_for_llm(assistant)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "8",
   "metadata": {},
   "source": [
    "Initialize GoogleSearchTool:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9",
   "metadata": {},
   "outputs": [],
   "source": [
    "google_tool = GoogleSearchTool()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "10",
   "metadata": {},
   "source": [
    "### Define the function for Currency Conversion:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "11",
   "metadata": {},
   "outputs": [],
   "source": [
    "def convert_currency(amount: float, rate: float) -> float:\n",
    "    return round(amount * rate, 2)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "12",
   "metadata": {},
   "source": [
    "### Frankfurter API Fallback Option"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13",
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_rate_frankfurter(amount: float, from_currency: str, to_currency: str) -> float:\n",
    "    \"\"\"\n",
    "    Fetch the exchange rate from the Frankfurter API and return the converted amount.\n",
    "    \"\"\"\n",
    "    import httpx\n",
    "\n",
    "    response = httpx.get(\n",
    "        \"https://api.frankfurter.app/latest\", params={\"amount\": amount, \"from\": from_currency, \"to\": to_currency}\n",
    "    )\n",
    "    response.raise_for_status()\n",
    "    return response.json()[\"rates\"][to_currency]"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "14",
   "metadata": {},
   "source": [
    "Define Work Directory:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "15",
   "metadata": {},
   "outputs": [],
   "source": [
    "workdir = Path(\"exchange_workspace\")\n",
    "workdir.mkdir(exist_ok=True)\n",
    "code_executor = LocalCommandLineCodeExecutor(work_dir=workdir)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "16",
   "metadata": {},
   "source": [
    "### Define Agents"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "17",
   "metadata": {},
   "outputs": [],
   "source": [
    "parser_agent = AssistantAgent(\n",
    "    name=\"ParserAgent\",\n",
    "    system_message=(\n",
    "        'You are an expert at extracting currency exchange requests. Given an input like \"Convert 100 USD to EUR\", extract the amount, source currency, and target currency in JSON format as: {\"amount\": 100, \"from\": \"USD\", \"to\": \"EUR\"}. '\n",
    "        \"If the user asks about anything other than currency conversion or exchange rates, politely state that you cannot help with that topic and can only assist with currency-related queries. \"\n",
    "        \"Do not attempt to answer unrelated questions or use tools for other purposes.\"\n",
    "    ),\n",
    "    llm_config=llm_config,\n",
    ")\n",
    "\n",
    "search_agent = AssistantAgent(\n",
    "    name=\"SearchAgent\",\n",
    "    system_message=\"You are a skilled web researcher. Given a source and target currency, search Google to find the most recent exchange rate. Respond with only the exchange rate as a float value.\",\n",
    "    llm_config={\"config_list\": llm_config.config_list},\n",
    ")\n",
    "\n",
    "frankfurter_agent = AssistantAgent(\n",
    "    name=\"FrankfurterAgent\",\n",
    "    system_message=(\n",
    "        \"You are a reliable agent that uses the Frankfurter API to return the converted amount. \"\n",
    "        \"Given amount, from_currency, and to_currency, call get_rate_frankfurter() and return the result as a float. \"\n",
    "        \"Do not perform any further calculations; just return the value from get_rate_frankfurter().\"\n",
    "    ),\n",
    "    functions=[get_rate_frankfurter],\n",
    "    code_execution_config={\"use_docker\": False},  # optionally sandboxed\n",
    "    llm_config={\"config_list\": llm_config.config_list},\n",
    ")\n",
    "\n",
    "response_agent = AssistantAgent(\n",
    "    name=\"ResponseAgent\",\n",
    "    system_message=(\n",
    "        \"You are a helpful assistant responsible for providing the final response to the user. \"\n",
    "        \"Given the converted amount, source currency, and target currency, respond in a clear and concise manner. \"\n",
    "        \"For example, if the user asks to convert 100 USD to EUR and the result is 92.5, respond with: \"\n",
    "        \"'100 USD is approximately 92.5 EUR.' \"\n",
    "        \"Once you've generated the summary, append the following marker: \"\n",
    "        \"==== FINAL ANSWER ====\"\n",
    "    ),\n",
    "    llm_config={\"config_list\": llm_config.config_list},\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "18",
   "metadata": {},
   "source": [
    "Register GoogleSearchTool to the search_agent:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "19",
   "metadata": {},
   "outputs": [],
   "source": [
    "search_api_key = os.getenv(\"GOOGLE_SEARCH_API_KEY\")\n",
    "search_engine_id = os.getenv(\"GOOGLE_SEARCH_ENGINE_ID\")\n",
    "\n",
    "assert search_api_key is not None, \"Please set GOOGLE_SEARCH_API_KEY environment variable\"\n",
    "assert search_engine_id is not None, \"Please set GOOGLE_SEARCH_ENGINE_ID environment variable\"\n",
    "\n",
    "gs_tool = GoogleSearchTool(\n",
    "    search_api_key=search_api_key,\n",
    "    search_engine_id=search_engine_id,\n",
    ")\n",
    "# Once initialized, register the tool with the assistant:\n",
    "gs_tool.register_for_llm(search_agent)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "20",
   "metadata": {},
   "source": [
    "### Define Termination Condition"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "21",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Any\n",
    "\n",
    "\n",
    "def is_termination_msg(msg: dict[str, Any]) -> bool:\n",
    "    content = msg.get(\"content\", \"\")\n",
    "    return (content is not None) and \"==== FINAL ANSWER ====\" in content"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "22",
   "metadata": {},
   "source": [
    "### Define Agent Collaboration Pattern"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "23",
   "metadata": {},
   "source": [
    "There are 2 Options in this notebook - either you get the exchange rate calculation using GoogleSearchTool, or you use Frankfurter API. That depends on the value of the USE_API variable:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "24",
   "metadata": {},
   "outputs": [],
   "source": [
    "USE_API = True  # Set to False to use GoogleSearchTool instead"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "25",
   "metadata": {},
   "outputs": [],
   "source": [
    "if USE_API:\n",
    "    agents = [parser_agent, frankfurter_agent, response_agent]\n",
    "    initial_agent = parser_agent\n",
    "else:\n",
    "    agents = [parser_agent, search_agent, response_agent]\n",
    "    initial_agent = parser_agent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "26",
   "metadata": {},
   "outputs": [],
   "source": [
    "pattern = AutoPattern(\n",
    "    initial_agent=initial_agent,\n",
    "    agents=agents,\n",
    "    user_agent=None,\n",
    "    group_manager_args={\n",
    "        \"llm_config\": llm_config,\n",
    "        \"is_termination_msg\": is_termination_msg,  # Ensure termination messages are handled\n",
    "    },\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "27",
   "metadata": {},
   "source": [
    "### Run the Group Chat:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28",
   "metadata": {},
   "outputs": [],
   "source": [
    "# === Run the group chat ===\n",
    "initial_prompt = input(\"Enter a currency conversion request (e.g., 'Convert 100 USD to EUR'): \")\n",
    "result, context, last_agent = initiate_group_chat(\n",
    "    pattern=pattern,\n",
    "    messages=initial_prompt,\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "front_matter": {
   "description": "This notebook demonstrates a fully autonomous, multi-currency conversion system.",
   "tags": [
    "tool calling",
    "tools",
    "currency",
    "google search"
   ]
  },
  "kernelspec": {
   "display_name": "fraud_detection",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
